#include <qicon.h>
#include <qdir.h>
#include <qbrush.h>
#include <qfont.h>
#include <qguiapplication.h>

#include "modelplaylists.h"

#include "debugmodule.h"

const QBrush ModelPlaylists::MISSING_BRUSH = QBrush(Qt::red);
const QBrush ModelPlaylists::DUPLICATE_BRUSH = QBrush(QColor("orange"));
const QBrush ModelPlaylists::INCOMPLETE_BRUSH = QBrush(Qt::magenta);
QIcon ModelPlaylists::DEFAULT_ICON = QIcon();
QFont ModelPlaylists::CHANGED_FONT = QFont();

ModelPlaylists::ModelPlaylists(QObject *parent) :
    QAbstractTableModel(parent)
{
    if (DEFAULT_ICON.isNull())
    {
        DEFAULT_ICON = QIcon(":icons/playlist");
        CHANGED_FONT.setBold(true);
    }
}

ModelPlaylists::~ModelPlaylists()
{
    qDeleteAll(m_lists);
}

int ModelPlaylists::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    else
        return m_lists.size();
}

int ModelPlaylists::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    else
        return MaxColIdx;
}

QVariant ModelPlaylists::data(const QModelIndex &index, int role) const
{
    switch (role)
    {
    case Qt::DisplayRole:
        switch(index.column())
        {
        case Filename:
        {
            const Playlist* list = m_lists.at(index.row());
            if (list->hasChanges())
                return QStringLiteral("*") + list->filename();
            else
                return list->filename();
        }
        case NoOfSongs:
            return m_lists.at(index.row())->songCount();
        case Missing:
            return m_lists.at(index.row())->missingCount();
        case Duplicate:
            return m_lists.at(index.row())->duplicateCount();
        case Incomplete:
            return m_lists.at(index.row())->incompleteCount();
        case Type:
            return m_lists.at(index.row())->typeString();
        }
        break;

    case Qt::ToolTipRole:
        if (index.column() == Filename)
            return m_lists.at(index.row())->fileInfo().absoluteFilePath();
        break;

    case Qt::TextAlignmentRole:
    {
        Qt::Alignment alignment = Qt::AlignVCenter;
        alignment |= index.column() == Filename ?
                    Qt::AlignLeft : Qt::AlignRight;
        return QVariant(alignment);
    }

    case Qt::FontRole:
        if (m_lists.at(index.row())->hasChanges())
            return CHANGED_FONT;
        break;

    case Qt::DecorationRole:
        if (index.column() == 0)
            return DEFAULT_ICON;
        break;

    case Qt::BackgroundRole:
        const Playlist* list = m_lists.at(index.row());
        if (list->missingCount() > 0)
            return MISSING_BRUSH;
        else if (list->duplicateCount() > 0)
            return DUPLICATE_BRUSH;
        else if (list->incompleteCount() > 0)
            return INCOMPLETE_BRUSH;
        break;
    }

    return QVariant();
}

QVariant ModelPlaylists::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
    {
        switch(section)
        {
        case Filename:
            return QStringLiteral("Dateiname");
        case NoOfSongs:
            return QStringLiteral("Songs");
        case Missing:
            return QStringLiteral("Fehlende Dateien");
        case Duplicate:
            return QStringLiteral("Duplikate");
        case Incomplete:
            return "Unvollständig";
        case Type:
            return QStringLiteral("Typ");
        }
    }

    return QVariant();
}

bool ModelPlaylists::addFile(const QString& i_filepath,
                             const QHash<QString, AudioFile*>& i_audioFiles)
{
    Playlist* pList = NULL;

    // Schon geladen?
    const QFileInfo fi(i_filepath);
    foreach (const Playlist* list, m_lists)
    {
        if (list->fileInfo() == fi)
            return false;
    }

    pList = Playlist::parse(i_filepath, i_audioFiles);

    if (pList)
    {
        beginInsertRows(QModelIndex(), m_lists.size(), m_lists.size());
        m_lists << pList;
        connect(pList, SIGNAL(dataChanged()), SLOT(playlistChanged()));
        endInsertRows();

        emit countChanged(rowCount());
    }

    return pList;
}

bool ModelPlaylists::addNewFile(const QString &i_filepath)
{
    // Schon geladen?
    const QFileInfo fi(i_filepath);
    for(int i = 0; i < m_lists.size(); i++)
    {
        if (m_lists.at(i)->fileInfo() == fi)
        {
            // Vorhandene Liste erst löschen
            beginRemoveRows(QModelIndex(), i, i);
            delete m_lists.takeAt(i);
            endRemoveRows();
            break;
        }
    }

    const Playlist::PlaylistType type = Playlist::getTypeFromFilename(i_filepath);

    if (type != Playlist::Unknown)
    {
        beginInsertRows(QModelIndex(), m_lists.size(), m_lists.size());
        Playlist* pList = new Playlist(i_filepath, type);
        m_lists << pList;
        connect(pList, SIGNAL(dataChanged()), SLOT(playlistChanged()));
        endInsertRows();

        return true;
    }

    emit countChanged(rowCount());
    return false;
}

void ModelPlaylists::remove(int i_idx)
{
    beginRemoveRows(QModelIndex(), i_idx, i_idx);
    delete m_lists.takeAt(i_idx);
    endRemoveRows();
    emit countChanged(rowCount());
}

void ModelPlaylists::clear()
{
    beginResetModel();
    qDeleteAll(m_lists);
    m_lists.clear();
    endResetModel();
    emit countChanged(rowCount());
}

void ModelPlaylists::setReplacePath(const QString &i_path, const QHash<QString, AudioFile *> &i_audioFiles)
{
    Playlist::sm_replacePath = i_path;

    // Backslash durch Slash ersetzen
    Playlist::sm_replacePath.replace('\\', '/');

    checkAudioFiles(i_audioFiles);
}

void ModelPlaylists::setLocalPath(const QString &i_path, const QHash<QString, AudioFile *> &i_audioFiles)
{
    Playlist::sm_localPath = QDir(i_path).absolutePath();
    checkAudioFiles(i_audioFiles);
}

void ModelPlaylists::checkAudioFiles(const QHash<QString, AudioFile *> &i_audioFiles)
{
    beginResetModel();

    for (int i = 0; i < m_lists.size(); i++)
    {
        m_lists[i]->checkAudioFiles(i_audioFiles);
    }

    endResetModel();
}

void ModelPlaylists::playlistChanged()
{
    if (Playlist* pList = qobject_cast<Playlist*>(sender()))
    {
        const int idx = m_lists.indexOf(pList);

        if (idx > -1)
        {
            emit dataChanged(index(idx,0), index(idx,MaxColIdx - 1));
        }
    }
}
